package com.jse.util.concurrent.new1.synchronizer;

import java.util.Random;
import java.util.concurrent.Semaphore;

import org.junit.Test;

/**
 * 参考http://www.java2s.com/Tutorials/Java/Java_Thread/0220__Java_Synchronizers.htm
 * 
 * 
 * Semaphore是一个互斥锁，不可重入，只有当获取许可的线程释放了，后面的线程才可以获取
 * 
 * 例如：JDBC的collection，当只有一个连接时，多个线程竞争连接，有个线程获取到之后，知道collection执行完，最后释放锁，后面的线程才可以执行
 * 
 * 有界缓冲就是使用这种技术，blockqueue中就是保持缓存资源的
 * @author Administrator
 */

public class SemaphoreTest {

	@Test
	public void testRead() throws Exception {
		Restaurant restaurant = new Restaurant(1);
	    for (int i = 1; i <= 5; i++) {
	      Customer c = new Customer(restaurant, i);
	      new Thread(c).start();
	    }
	    
//	    Thread.sleep(3000);
	}
	
	class Restaurant {
		Semaphore semaphore;
		
		public Restaurant(int count) {
			//Count表示许可的数量
			semaphore = new Semaphore(count);
		}
		
		public void getTable(int id) {
			System.out.println("customer-" + id + "正在获取锁");
			try {
				semaphore.acquire();
				System.out.println("customer-" + id + "==============已经获取到锁");
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
		public void eatUp() {
			semaphore.release();
		}
	}
	
	class Customer implements Runnable {
		private int id;
		private Restaurant resraurant;
		private final Random random = new Random();
		
		public Customer(Restaurant restaurant, int id) {
			this.resraurant = restaurant;
			this.id = id;
		}
		
		@Override
		public void run() {
			resraurant.getTable(id);
			try {
				int eatingTime = random.nextInt(30) + 1;
			      System.out.println("Customer #" + this.id + "  will eat for " + 1 + "  seconds.");
//			      Thread.sleep(1 * 1000);
			      System.out.println("Customer #" + this.id + "  is done  eating.");
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				resraurant.eatUp();
			}
		}
	}
}
